using System;
using System.Collections.Generic;
using System.Linq;
using AudioStudio;
using BitBenderGames;
using Cinemachine;
using com.yoozoo.gta.Gameplay.PVE;
using DG.Tweening;
using Extensions;
using GameFramework.Battle.Core;
using Gameplay.PVE;
using Gameplay.PVE.Data;
using Gameplay.PVE.Entity;
using Gameplay.PVE.Skill;
using Gameplay.PVE.TurnBase;
using Gameplay.PVE.Utils;
using NpcFramework;
using Unity.Mathematics;
using UnityEditor;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Playables;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.UI;
using WorldMap;
using XLua;
using Yoozoo.Framework.Managers;
using Yoozoo.Gameplay;
using Yoozoo.Gameplay.Liberty;
using Yoozoo.Gameplay.Liberty.AI;
using Yoozoo.Gameplay.RTS;
using Yoozoo.Gta.Common;
using Yoozoo.HRP.Runtime;
using Yoozoo.Managers;
using Yoozoo.Managers.ResourceManagerV2.Runtime;
using Yoozoo.Mars.Got;
using Yoozoo.UI.YGUI;
using BattleUnit = Gameplay.PVE.Entity.BattleUnit;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;
using Sequence = GameFramework.Battle.Core.Sequence;
using SkillBase = Gameplay.PVE.Skill.SkillBase;
using SkillInitiative = Gameplay.PVE.Skill.SkillInitiative;
using UnitData = Gameplay.PVE.Data.UnitData;

namespace Gameplay.PVE
{
    public class PveManager
    {
        private static PveManager p_instance;
        private bool inited = false;
        private bool enterScene = false;
        private UnitManager unitManager;
        private PveResourceManager resourceManager;
        private OperationManager operationManager;
        private PveFindPathManager findPathManager;
        private PveDropManager dropManager;
        private TimeManager timeManager;
        private SpecialCaseManager specialCaseManager;
        private PveUIDataManager uiDataManager;
        private PveMap pveMap;

        private PveCameraManager cameraManager;
        private PveCardManager cardManager;

        private int vehicleCount = 0;
        private float stageToNextTime;
        private float checkVehicleTime;

        private List<int> selfRPGReadyList = new List<int>();

        public bool IsStageActive; //是否正在战斗
        public bool rpgStart;

        public bool rpgFinish
        {
            get { return false; }
        }

        public bool isInRpg;
        public bool isToRpg; //是否正要前往rpg关卡
        public bool isToRpgTransition; //是否正在前往
        public bool isInTimeline;
        private bool isPveToNext = false;

        public int rpgLevelPassCount = -1;

        public bool isManualMoving = false;

        public bool isSwitchToRpg = false;

        public bool isSwitchToPve = false;

        public int RpgLevelId;

        public bool isInPve
        {
            get { return !isInRpg && !isToRpg; }
        }


        private float focusBattleTime;

        private Dictionary<int, bool> stagePreparedDic = new Dictionary<int, bool>();


        public BattleUnit mainUnit;
        private bool isInSpecialCase;


        public float teamEnergy = 0;

        private List<Vector3> rpgAttackPositions;

        public float TimeSpeed = 1;

        private float leftTime;
        private int leftSecond;

        public bool isEnemyStartSearch = false;

        private float stageStartTime;
        public float stageActiveTime;
        public float bossHpPercent;


        public static int frame = 0;
        public bool IsAuto;

        private List<int> activeStage = new List<int>();

        public int pveWantedScore;

        private bool isShowFighting = false;

        public Action onBattleFinish;

        public PveNpcViewLayer PveNpcViewLayer { private set; get; }
        private GameObject npcManagerObj;

        public static PveManager Instance
        {
            get
            {
                if (p_instance == null)
                {
                    p_instance = new PveManager();
                }

                return p_instance;
            }
        }

        public void HideOrShowBloodBar()
        {
            var team1 = unitManager.GetAllUnitByTeam(0);
            var team2 = unitManager.GetAllUnitByTeam(2);
            foreach (var unit in team1)
            {
                unit.HideOrShowBloodBar();
            }

            foreach (var unit in team2)
            {
                unit.HideOrShowBloodBar();
            }
        }

        public void Init(int stageType = 0)
        {
            unitManager = UnitManager.Instance;

            PveUtils.pveUnitLayer = LayerMask.NameToLayer(PveString.pveUnitLayer);
            PveUtils.pveCameraColliderLayer = LayerMask.NameToLayer(PveString.pveCameraColliderLayer);
            PveUtils.commanderHairLayer = LayerMask.NameToLayer("commanderHair");
            PveUtils.agentHairLayer = LayerMask.NameToLayer("AgentHair");

            inited = true;
            timeManager = TimeManager.Instance;
            findPathManager = PveFindPathManager.Instance;
            findPathManager.Initialize();
            resourceManager = PveResourceManager.Instance;
            resourceManager.Initialize(() =>
            {
#if UNITY_EDITOR

#endif
                PveUtils.HasShownSkillVideo = true;
                //EnterPveBattle();
            });
            InitClass();

            AddEventListeners();
        }

        private void AddEventListeners()
        {
            GTAGameStart.eventManager.AddEvent(ClientEvent.ChangePveSceneFog, (LuaTable b) =>
            {
                var flag = b.Get<int, bool>(1);
                pveMap.EnableFogEffect(flag);
            });
        }

        private void RemoveEventListeners()
        {
            GTAGameStart.eventManager.RemoveEvent(ClientEvent.ChangePveSceneFog);
        }

        public void EnterPveBattle()
        {
            if (enterScene)
            {
                return;
            }

            InitCamera();
            specialCaseManager = SpecialCaseManager.Instance;
            specialCaseManager.Initialize();
            dropManager = new PveDropManager();
            dropManager.Initialize();
            cardManager = PveCardManager.Instance;
            cardManager.Init();
            if (PveScene.IsTest)
            {
                //StartTest(PveMapEditor.Instance.MapId);
            }
            else
            {
                Start();
            }

            PveEffectManager.Instance.Initialize();
            HRPHelper.EnableBaseScene(HRPHelper.PveRenderScene);
            SetRimLightCameraDir setRimLightCameraDir =
                HRPHelper.PveRenderScene.transform.GetComponentInChildren<SetRimLightCameraDir>();
            if (setRimLightCameraDir != null)
            {
                setRimLightCameraDir.SceneCamera =
                    PveResourceManager.Instance.GetPVECamera().GetComponentInChildren<Camera>();
            }

            enterScene = true;
        }

        public void Start()
        {
            isSwitchToRpg = false;
            isSwitchToPve = false;
            PveResourceManager.Instance.IsReady = true;
#if UNITY_EDITOR
            QualitySettings.antiAliasing = 8;
#endif
            InitMap();
            ResidentHandler.Inst.GetFunction("pveManager.StartPVE").Action(0);
            StartPveScene();
            //unitManager.ResLoadComplete();
        }

        public void StartPveScene()
        {
            pveMap.StartPve(startPosition);
            pveMap.PlayHangMusic();
            mainUnit = unitManager.AddAFKMyUnit(41004, stageId) as BattleUnit;
            cameraManager.StartPve(mainUnit);
        }


        public int pveStageId = 0;
        public int rpgStageId = 0;

        public int stageId
        {
            get
            {
                if (isToRpg || isInRpg)
                {
                    return rpgStageId;
                }

                return pveStageId;
            }
        }

        public void InitNpcFramework()
        {
            PveNpcViewLayer = new PveNpcViewLayer();
        }

        public BattleUnit GetUnit(int id)
        {
            return unitManager.GetUnit(id);
        }

        public ObstacleUnit GetObstacleUnit(int id)
        {
            return unitManager.GetObstacleUnit(id);
        }

        public List<Vector3> GetVehiclePath(int stage)
        {
            bool isNext = stage > stageId;
            return pveMap.GetCarRoad(isNext);
        }


        public Vector3 startPosition = new Vector3(0, 0, 0);

        private void InitCamera()
        {
            cameraManager = new PveCameraManager();
            cameraManager.Init();
        }

        private void InitMap()
        {
            pveMap = new PveMap();
            pveMap.Init(startPosition);
        }

        private float lastPercent;

        public void UpdateLoadingProgress(float percent, string msg)
        {
            ResidentHandler.Inst.GetFunction("pveManager.UpdateLoadingProgress").Action(percent * 100, msg);
        }


        private Vector3 afkMainUnitPosition;
        private Vector3 afkMainUnitForward;


        //挂机切战斗统一走这两个接口
        public void EndHanging()
        {
            BlueprintUtils.TimelineManager?.StopCurrentTimeline();
            if (!PveScene.isInited)
            {
                return;
            }

            IsStageActive = false;
            pveMap.CreateModelLight(true);
            afkMainUnitPosition = mainUnit.Data.position;
            afkMainUnitForward = mainUnit.Data.forward;
            //pveMap.HangLightToRpg();
            RenderSettings.fog = false;
            DynamicNavMeshBuilder.Instance.enabled = false;
            PveResourceManager.Instance.ClearPathPoints();
            //pveMap.StartRpgMusic();
            pveMap.StopHangMusic();
            //PveNpcFrameworkMgr.RemoveAllNpc(false);

        }

        public void StartHanging()
        {
            if (!PveScene.isInited)
            {
                return;
            }

            pveMap.CreateModelLight(false);
            pveMap.RpgLightToHang();
            IsStageActive = true;
            isToRpg = false;
            isInRpg = false;
            onBattleFinish?.Invoke();

            HRPHelper.ClearRenderScene();
            HRPHelper.EnableBaseScene(HRPHelper.PveRenderScene);

            SetRimLightCameraDir setRimLightCameraDir =
                HRPHelper.PveRenderScene.transform.GetComponentInChildren<SetRimLightCameraDir>();
            if (setRimLightCameraDir != null)
            {
                setRimLightCameraDir.SceneCamera =
                    PveResourceManager.Instance.GetPVECamera().GetComponentInChildren<Camera>();
            }

            pveMap.StopRpgMusic();
            pveMap.PlayHangMusic();
            pveMap.SwitchToHangRenderSetting();
            isSwitchToRpg = false;
            RenderSettings.fog = true;


            IsStageActive = true;
            unitManager.AddAFKMyUnit(41004, stageId);
            mainUnit = unitManager.GetAfkMainUnit();
            mainUnit.gameObject.transform.position = afkMainUnitPosition;
            mainUnit.Data.position = afkMainUnitPosition;
            mainUnit.Data.forward = afkMainUnitForward;
        }

        public void RebindMainUnitToCamera()
        {
            if (!PveScene.isInited)
            {
                return;
            }

            cameraManager.StartPve(mainUnit);
        }

        public void ShowMap()
        {
            if (!PveScene.isInited)
            {
                return;
            }

            pveMap?.Show();
        }

        public void HideMap()
        {
            if (!PveScene.isInited)
            {
                return;
            }

            pveMap?.Hide();
        }

        public Vector3 GetStagePosition()
        {
            return pveMap.GetStagePosition();
        }

        public Vector3 GetRpgStageCenterPosition()
        {
            return pveMap.GetRpgStageCenterPosition();
        }


        private Vector4 rpgStageRegion;

        /// <summary>
        /// xMax,xMin,zMax,zMin
        /// </summary>
        /// <returns></returns>
        public Vector4 GetRpgStageRegion()
        {
            if (rpgStageRegion != Vector4.zero)
            {
                return rpgStageRegion;
            }

            var center = GetRpgStageCenterPosition() + new Vector3(1.08f, 0, -0.67f);
            var width = 18f;
            var height = 12.34f;
            rpgStageRegion = new Vector4(center.x + width / 2, center.x - width / 2, center.z + height / 2,
                center.z - height / 2);
            return rpgStageRegion;
        }

        public bool IsInBattleRegion(Vector3 position)
        {
            var region = GetRpgStageRegion();
            if (position.x > region.x || position.x < region.y || position.z > region.z || position.z < region.w)
            {
                return false;
            }

            return cameraManager.IsInBattleCameraScreen(position);
        }

        public Vector3 GetRestrictedPositionByBattleRegion(Vector3 position)
        {
            var pos = position;
            var region = GetRpgStageRegion();
            pos.x = Mathf.Min(region.x, pos.x);
            pos.x = Mathf.Max(region.y, pos.x);
            pos.z = Mathf.Min(region.z, pos.z);
            pos.z = Mathf.Max(region.w, pos.z);
            return cameraManager.GetRestrictedPositionByCameraScreen(pos);
        }

        public float RpgStageRegionMinX = -10;
        public float RpgStageRegionMaxX = 4;
        public float RpgStageRegionWidth = 4;

        public int GetRpgRoadTypeByPosition(Vector3 position)
        {
            var mid = GetRpgStageMidRegion();
            if (position.z > mid.w)
            {
                return 0;
            }
            else if (position.z < mid.z)
            {
                return 2;
            }

            return 1;
        }

        public Vector4 GetRpgStageRegionByRoadType(int type)
        {
            if (type == 0)
            {
                return GetRpgStageTopRegion();
            }
            else if (type == 1)
            {
                return GetRpgStageMidRegion();
            }
            else
            {
                return GetRPgStageBottomRegion();
            }
        }

        public Vector4 GetRpgStageTopRegion()
        {
            var center = GetRpgStageCenterPosition();
            return new Vector4(center.x + RpgStageRegionMinX, center.x + RpgStageRegionMaxX,
                center.z + RpgStageRegionWidth / 2, center.z + RpgStageRegionWidth * 3 / 2);
        }

        public Vector4 GetRpgStageMidRegion()
        {
            var center = GetRpgStageCenterPosition();
            return new Vector4(center.x + RpgStageRegionMinX, center.x + RpgStageRegionMaxX,
                center.z - RpgStageRegionWidth / 2, center.z + RpgStageRegionWidth / 2);
        }

        public Vector4 GetRPgStageBottomRegion()
        {
            var center = GetRpgStageCenterPosition();
            return new Vector4(center.x + RpgStageRegionMinX, center.x + RpgStageRegionMaxX,
                center.z - RpgStageRegionWidth * 3 / 2, center.z - RpgStageRegionWidth / 2);
        }

        public Vector3 GetRpgCameraCenterPosition()
        {
            return pveMap.GetRpgStageCenterPosition();
        }

        public List<Vector3> GetMyRoadPathToRpg(int id)
        {
            return pveMap.GetMyRoadPathToRpg(id);
        }


        public List<Vector3> GetMortalRoadPath(Vector3 position, int stage)
        {
            bool isNext = stage > stageId;
            return pveMap.GetMortalRoadPath(position, isNext);
        }


        private Transform awardTransform;
        private Vector3 awardPosition;
        private GameObject pveBattleRoot;
        private List<GameObject> uiFlyObjs = new List<GameObject>(128);
        private Camera uiCam;
        private List<int> flyTasks = new List<int>();


        public void PrepareAStar(Vector3 position)
        {
            if (!PveScene.isInited)
            {
                return;
            }

            pveMap.rpgPosition = position;
        }

        public void Update()
        {
        }

        private Transform costBar;
        private float costInterval;
        private GameObject energyMaxEffect;
        private Transform cardParent;


        public void BeforeUpdate()
        {
            unitManager?.BeforeUpdate();
        }

        public void LateUpdate()
        {
            unitManager?.LateUpdate();
        }

        public GameObject GetSceneRootPrefab()
        {
            return pveMap.GetSceneRootPrefab();
        }

        private float gameTimeScaleBeforePause = 0;
        private float logicTimeScaleBeforePause = 0;
        private float gameTimeScaleBeforeTimelinePause = 0;
        private float logicTimeScaleBeforeTimelinePause = 0;
        private bool isStageActiveBeforePause = false;
        private bool isStageActiveBeforeTimelinePause = false;
        private bool isPause = false;
        private bool isTimelinePause = false;

        private UnitBase timelineUnit;

        public void OnTimelineStart(UnitBase unit)
        {
            timelineUnit = unit;
        }

        public void OnTimelineEnd()
        {
            if (timelineUnit != null)
            {
                timelineUnit.Transmit(ETransmitType.TimelineEnd);
            }

            timelineUnit = null;
        }

        public void TimelinePause()
        {
            if (isTimelinePause)
            {
                return;
            }

            isTimelinePause = true;
            gameTimeScaleBeforeTimelinePause = TimeManager.gameTimeScale;
            logicTimeScaleBeforeTimelinePause = TimeManager.logicTimeScale;
            isStageActiveBeforeTimelinePause = IsStageActive;
            TimeManager.gameTimeScale = 0;
            TimeManager.logicTimeScale = 0;
            IsStageActive = false;
            unitManager.Pause();
            cameraManager.StopShake();
            PveEffectManager.Instance.Pause();
            operationManager.Pause();
            if (timelineUnit is BattleUnit unit)
            {
                unit.Resume();
            }
        }

        public void TimelineResume()
        {
            isTimelinePause = false;
            TimeManager.gameTimeScale = gameTimeScaleBeforeTimelinePause;
            TimeManager.logicTimeScale = logicTimeScaleBeforeTimelinePause;
            IsStageActive = isStageActiveBeforeTimelinePause;
            unitManager.Resume();
            PveEffectManager.Instance.Resume();
            operationManager.Resume();
        }

        public void LogicPause()
        {
            PveScene.isPause = true;
            IsStageActive = false;
            TimeManager.logicTimeScale = 0;
            unitManager.LogicPause();
            cameraManager.StopShake();
            if (isInRpg)
            {
                operationManager.StopAction();
                operationManager.StopDrag();
            }
        }

        public void LogicResume()
        {
            PveScene.isPause = false;
            TimeManager.logicTimeScale = 1;
            IsStageActive = true;
        }

        public void ResumeAfk()
        {
            HCameraManager.EnableCamera(PveCameraManager.Instance.pveMainCamera.GetComponent<HCamera>());
            pveMap?.PlayHangMusic();
        }

        public void SetCameraEnable()
        {
            HCamera cam = PveCameraManager.Instance.pveMainCamera.GetComponent<HCamera>();
            if (cam != null)
                cam.SetEnable(true);
        }

        public void PauseAfk()
        {
            pveMap?.StopHangMusic();
        }

        private void InitClass()
        {
            ClassManager.Store<Selector>(14);
            ClassManager.Store<Parallel>(14);
            ClassManager.Store<Sequence>(14);
            ClassManager.Store<Inverter>(14);
            ClassManager.Store<Sequencer>(14);
            ClassManager.Store<IsHaveLockTarget>(10);
            ClassManager.Store<MoveToAttack>(10);
            ClassManager.Store<SearchTarget>(10);
            ClassManager.Store<IsAttackInRange>(10);
            ClassManager.Store<IsObeyingOrder>(10);
            ClassManager.Store<HasBattleInSight>(10);
            ClassManager.Store<Escape>(10);
            ClassManager.Store<MortalAction>(10);
            ClassManager.Store<Wait>(10);
            ClassManager.Store<VehicleAction>(10);
            ClassManager.Store<HasObstacleFront>(10);
            ClassManager.Store<CanAutoUseSkill>(10);
            ClassManager.Store<UseSkill>(10);
            ClassManager.Store<IsInitiative>(10);

            ClassManager.Store<BattleUnit>(10);
            ClassManager.Store<BehaviorComponent>(10);
            ClassManager.Store<MoveComponent>(10);
            ClassManager.Store<SearchComponent>(10);
            ClassManager.Store<RenderComponent>(10);
            ClassManager.Store<ControlComponent>(10);
            ClassManager.Store<BattleComponennt>(10);
            ClassManager.Store<HudComponent>(10);

            ClassManager.Store<UnitData>(10);
            ClassManager.Store<UnitOrder>(10);
            ClassManager.Store<AddOrderTransmitArg>(10);
            ClassManager.Store<ModelActionTransmitArg>(20);
            ClassManager.Store<SkillTransmitArg>(10);
            ClassManager.Store<HatredSearchTransmitArg>(10);

            ClassManager.Store<SkillInitiative>(10);
            ClassManager.Store<SkillBullet>(50);

            ClassManager.Store<MortalRoadPath>(10);
            ClassManager.Store<BattleUnitRoadPath>(10);

            ClassManager.Store<DropItem>(100);
        }

        public void Dispose()
        {
            if (!inited)
            {
                return;
            }

            inited = false;
            RemoveEventListeners();
            PveEffectManager.Instance.Dispose();
            unitManager?.Dispose();
            unitManager = null;
            operationManager?.Dispose();
            operationManager = null;
            findPathManager?.Dispose();
            findPathManager = null;
            dropManager.Dispose();
            dropManager = null;
            timeManager.Dispose();
            timeManager = null;
            specialCaseManager?.Dispose();
            specialCaseManager = null;
            cameraManager?.Dispose();
            cameraManager = null;
            PveFlyTextManager.Instance.Dispose();

            //卸载资源
            resourceManager?.Dispose();
            resourceManager = null;
            //卸载表现层
            if (PveNpcViewLayer != null)
            {
                PveNpcViewLayer.Dispose();
            }

            if (npcManagerObj != null)
            {
                GameObject.DestroyImmediate(npcManagerObj);
                npcManagerObj = null;
            }

            // 涉及到根节点销毁，请等待所有附加节点释放完成后销毁，否则会导致资源泄露
            pveMap?.Dispose();
            pveMap = null;

            IsStageActive = false;
            p_instance = null;

            TimeManager.logicTimeScale = 1;
            Time.timeScale = 1;
        }
    }
}